package com.zhouyu.nettysvr.handler;

import com.zhouyu.nettysvr.dao.ConnectionDao;
import com.zhouyu.nettysvr.msgdto.MyMsg;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @Description:解码之后的业务处理
 */
@Component
@Log4j2
public class NettyServerHandler extends SimpleChannelInboundHandler<MyMsg> {

    @Autowired
    ConnectionDao connectionDao;

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("【服务端】建立连接，客户端ip:{}", ctx.channel().remoteAddress());
        super.channelInactive(ctx);
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        //检查连接是否存在，保存长连接
        connectionDao.createConnection(ctx);
        super.channelRegistered(ctx);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        connectionDao.closeConnection(ctx);
        super.channelUnregistered(ctx);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
    }

    /**
     * @param channelHandlerContext:
     * @param baseMessage:
     * @return
     * @description :这个方法执行完毕后自动释资源,可以看源码
     * @author zhouyu
     * @date 2020/5/9 12:30
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, MyMsg baseMessage) throws Exception {
        log.info("【服务端收到拆包解码后的消息】:{}", baseMessage);
        SocketChannel channel = (SocketChannel) channelHandlerContext.channel();
        if(baseMessage.getType()==1){
            //处理心跳
            sendPongMsg(channelHandlerContext);
        }else {
            //处理业务(工厂+策略模式)
            /**
             * 参考：https://blog.csdn.net/weixin_43167418/article/details/102675271
             */
            handleData(channelHandlerContext,baseMessage);
        }
    }

    /**
     * 心跳闲置事件
     * @param ctx 通道
     * @param evt 事件
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if(evt instanceof IdleStateEvent){
            IdleStateEvent idleStateEvent= (IdleStateEvent) evt;
            switch (idleStateEvent.state()){
                case ALL_IDLE:
                    handleAllIdle(ctx);
                    break;
                case READER_IDLE:
                    handleReaderIdle(ctx);
                    break;
                case WRITER_IDLE:
                    handleWriterIdle(ctx);
                    break;
            }
        }else {
            super.userEventTriggered(ctx,evt);
        }
    }

    private void handleData(ChannelHandlerContext ctx,MyMsg msg){

    }

    private void sendPongMsg(ChannelHandlerContext ctx){
        //todo 回复心跳
        log.info("【服务端收到心跳包】,回复客户端");
    }

    protected void handleReaderIdle(ChannelHandlerContext ctx) {
        //读超时，放弃读
    }

    protected void handleWriterIdle(ChannelHandlerContext ctx) {
        //写超时，放弃写
    }

    protected void handleAllIdle(ChannelHandlerContext ctx) {
       //读写超时，断开连接
    }
}
